package system

import (
	"errors"
	"os"
	"syscall"
	"unsafe"
)

var (
	kernel32         = syscall.MustLoadDLL("kernel32.dll")
	procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
	procCreateMutexA = kernel32.MustFindProc("CreateMutexA")
)

//错误重定向的目标文件
var stdErrFileHandle *os.File

//进程锁
type NamedLock struct {
	f uintptr
}

//将os.Stderr写入文件
//windows下真实效果是panic输出的消息转移到了文件
func StdErrorToFile(file *os.File) error {
	//延长生命周期
	_ = stdErrFileHandle
	stdErrFileHandle = file
	sh := syscall.STD_ERROR_HANDLE
	v, _, err := procSetStdHandle.Call(uintptr(sh), uintptr(file.Fd()))
	if v == 0 {
		return err
	}
	return nil
}

//进程锁，加锁
func (l *NamedLock) Lock(name string) bool {
	id, _, err := procCreateMutexA.Call(0, 1, uintptr(unsafe.Pointer(&name)))
	l.f = id
	return errors.Is(err, syscall.Errno(0))
}

//进程锁，解锁
func (l *NamedLock) Unlock() {
	syscall.CloseHandle(syscall.Handle(l.f))
}